<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Developer Tools - Wave Framework</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width"/> 
		<link type="text/css" href="../style.css" rel="stylesheet" media="all"/>
		<link rel="icon" href="../../favicon.ico" type="image/x-icon"/>
		<link rel="icon" href="../../favicon.ico" type="image/vnd.microsoft.icon"/>
	</head>
	<body>
	
		<h1>About Developer Tools</h1>
		
			<ul>
				<li><a href="#index-introduction">Introduction</a></li>
				<li><a href="#index-adminer">Adminer</a></li>
				<li><a href="#index-php-information">PHP Information</a></li>
				<li><a href="#index-api-information">API Information</a></li>
				<li><a href="#index-log-reader">Log Reader</a></li>
				<li><a href="#index-filesystem-cleaner">Filesystem Cleaner</a></li>
				<li><a href="#index-backup">Backup</a></li>
				<li><a href="#index-debugger">Debugger</a></li>
				<li><a href="#index-compatibility-test">Compatibility Test</a></li>
				<li><a href="#index-updater">Updater</a></li>
				<li><a href="#index-test-suite">Test Suite</a></li>
				<li><a href="#index-calling-tools-through-factory">Calling Tools Through Factory</a></li>
			</ul>
		
			<h2 id="index-introduction">Introduction</h2>
			
				<p>Wave Framework comes with a suite of administrative tools that are useful for debugging, maintenance, compatibility testing and more. These scripts are all stored in /tools/ subfolder and every script is protected with a username and password. Username and password of most of those tools are stored in main /config.ini file and are used regardless whether limiter-authentication is turned on or off in configuration. Despite being protected by username and password, it is highly recommended to remove developer tools subfolder entirely before deploying project live.</p>
				
				<p>Some developer tools are also integrated in Wave Framework Factory and can be called using that factory. For example, you can return an index of files recursively from a folder or delete all files from a specific folder, as long as PHP has rights to this activity. Details about such functionality called through Wave Framework API are in the very bottom of this document.</p>
				
			<h2 id="index-adminer">Adminer</h2>
			
				<p><b>Location: /tools/adminer.php</b></p>
				
				<p>Adminer is an open-source database administration tool that runs from a single script. This is useful for production servers that do not have PHPMyAdmin or other similar environments installed and it doesn't require a set-up or anything of the sort. Adminer is not protected by http-authentication-username and http-authentication-password and instead asks for database host, username and password. It is highly recommended to remove this script before deploying the project live.</p>
				
			<h2 id="index-php-information">PHP Information</h2>
			
				<p><b>Location: /tools/php-info.php</b></p>
				
				<p>This script is essentially a password-protected wrapper for phpinfo() function and it displays information about extensions, PHP settings, server variables and setup in general. It is highly recommended to remove this script before deploying the project live.</p>
				
			<h2 id="index-api-information">API Information</h2>
			
				<p><b>Location: /tools/api-info.php</b></p>
			
				<p>This script lists all controllers and their methods, as well as all API profiles that can use these methods. This is meant for an overview of API commands for documentation purposes or otherwise. It shows all API commands based on what their 'www-command' value should be as well as displays comments that have been written in the header of these methods. It is possible to also show API commands per API profile.</p>
				
			<h2 id="index-log-reader">Log Reader</h2>
			
				<p><b>Location: /tools/log-reader.php</b></p>
				
				<p>Log reader shows a lot of detailed information about each HTTP request, including input data sent with the request, performance information about how long the request took and how much memory it used.</p>

				<p>By default the log reader accesses log file of the current hour, but if you define a GET variable 'log' with the request, then it can access older logs as well, if they exist. For example, this request would return logs from 11th hour on January 15, 2012:</p>
				
				<p>http://www.example.com/tools/log-reader.php?log=2012-01-15-11</p>
				
				<p>These are the details that are included in most log entries:</p>
				
				<ul>
					<li><b>request-id</b> - Unique request identifier set by the server</li>
					<li><b>request</b> - This stores the URI that client requested</li>
					<li><b>microtime</b> - Timestamp of the request in milliseconds</li>
					<li><b>time</b> - UNIX timestamp of the request time</li>
					<li><b>datetime</b> - Stores request datetime in format 'Y-m-d H:i:s'</li>
					<li><b>ip</b> - Stores IP of the client that made the request</li>
					<li><b>forwarded-client-ip/remote-addr</b> - Additional IP values when proxy is used</li>
					<li><b>user-agent</b> - This stores user agent string of the client</li>
					<li><b>referrer</b> - Referrer URL that made the request</li>
					<li><b>get</b> - GET variables submitted by client</li>
					<li><b>post</b> - POST variables submitted by client</li>
					<li><b>files</b> - FILES variables submitted by client</li>
					<li><b>cookie</b> - COOKIE variables submitted by client</li>
					<li><b>execution-time</b> - This stores how long the request took in seconds</li>
					<li><b>memory-peak-usage</b> - This stores the peak usage of memory during the request</li>
					<li><b>cpu-user-usage/cpu-system-usage</b> - CPU usage diagnostics</li>
					<li><b>system-load</b> - This stores system load number (that is one minute old)</li>
					<li><b>api-profile</b> - This is the 'system identifier' that made the request</li>
					<li><b>response-code</b> - HTTP response code for the request</li>
					<li><b>error</b> - If PHP encountered an error, this stores the error message</li>
					<li><b>category</b> - This is for categorizing various calls, used mainly by <a href="gateway.htm">Index Gateway</a> to separate requests of different type</li>
					<li><b>cache-used</b> - Flag that defines whether cache has been used with this request</li>
					<li><b>database-query-count</b> - If set, this stores how many queries were sent to database</li>
					<li><b>content-length</b> - This is approximate length of data returned to client</li>
				</ul>
				
				<p>Log Reader also has a mode that reads the Internal Log of Wave Framework. Internal Log is custom log that the developer can write to from Controllers and other parts of the system. To read the Internal Log, you have to change the request to '/tools/log-reader.php?internal' or select the Internal Log mode from the Log Reader page.</p>
				
				<p>Log Reader is also used to display log of <a href="guide_api.htm">API</a> calls made over HTTP. API Log is a custom log that is populated if 'api-logging' is allowed from <a href="configuration.htm">Configuration</a>. Compared to Internal Log and HTTP request Log, API log is not a serialized array and simply carries three files in '/filesystem/log/api.log' file: Timestamp when the request was made, API Profile that made the request and the 'www-command' that was sent. This log can be used to easily calculate statistics and traffic for API profiles.</p>
				
			<h2 id="index-filesystem-cleaner">Filesystem Cleaner</h2>
			
				<p><b>Location: /tools/cleaner.php</b></p>
				
				<p>Cleaner is used to delete various temporary files - that have been generated by Wave Framework - from the <a href="filesystem.htm">Filesystem</a> - and it returns log of all files that have been removed. Script requires a specific mode to work properly and all the modes are available when the script is run without a mode set. It can clean the entire '/filesystem/' folder and subfolders, only temporary files from '/filesystem/' folder and subfolders or specific folders from '/filesystem/'.</p>
				
				<p>These are all the cleaner modes that are available:</p>
				
				<ul>
					<li><b>all</b> - Empties all folders from /filesystem/ directory.</li>
					<li><b>maintenance</b> - Empties all non-critical folders from /filesystem/ directory (including sessions).</li>
					<li><b>cache</b> - Empties all cache-related folders from /filesystem/ directory.</li>
					<li><b>output</b> - Output cache</li>
					<li><b>images</b> - Image cache</li>
					<li><b>resources</b> - Resource file cache.</li>
					<li><b>custom</b> - Custom cache.</li>
					<li><b>tags</b> - Cache tags.</li>
					<li><b>sessions</b> - Session storage.</li>
					<li><b>messenger</b> - State messenger.</li>
					<li><b>errors</b> - Error reports.</li>
					<li><b>logs</b> - Log files.</li>
					<li><b>tmp</b> - Temporary files.</li>
					<li><b>limiter</b> - Request limiter storage.</li>
					<li><b>tokens</b> - API access tokens.</li>
					<li><b>backups</b> - Backup archives.</li>
					<li><b>updates</b> - Update archives.</li>
					<li><b>data</b> - Custom database folder.</li>
					<li><b>userdata</b> - Custom userdata folder.</li>
					<li><b>keys</b> - Folder for certificates and keys.</li>
					<li><b>static</b> - Filesystem static folder.</li>
				</ul>
				
				<p>It is also possible to send a cut-off timestamp, by assigning a 'cutoff' GET variable to the request. This Unix timestamp will be compared against every file in those assigned folders and if the file is newer or has been modified since that timestamp, then the file is not deleted.</p>

			<h2 id="index-backup">Backup</h2>
			
				<p><b>Location: /tools/backup.php</b></p>
				
				<p>This script simply creates a backup of all of your files in the project folder and places them in '/filesystem/backups/' subfolder. Backup can be run in two modes that have to be defined when making a request to the script (these modes can also be selected from the script, if mode is not defined). These modes are defined with GET variables and are 'all' and 'system'. First mode creates backup of everything and second mode only creates backup of all files, except those that are in '/filesystem/' directory.</p>
				
				<p>Backup creates a Zip archive with a date-specific filename of {Y-m-d-H-i-s}.zip.tmp and to open this archive you have to download it over FTP and rename it to .zip extension, since HTTP requests to *.tmp files are blocked by default.</p>
				
			<h2 id="index-debugger">Debugger</h2>
			
				<p><b>Location: /tools/debugger.php</b></p>
				
				<p>This is a script that collects error messages that have been written to <a href="filesystem.htm">Filesystem</a>. It also provides method to easily delete the error log about a specific error message, once it is considered 'fixed'. This script should be checked every now and then to test and make sure that there are no outstanding problems in the system.</p>
				
				<p>Each error message is categorized based on IP and user agent string signature, which allows to separate errors generated by different systems, users or developers.</p>
				
				<p>Wave Framework logs all PHP error messages. When Wave Framework encounters a fatal error, then it displays an error message specifying such to the user. Wave Framework suppresses warnings and lesser error messages, but still logs them so that they are visible with this Debugger script. It is a good development practice to make sure all error messages and warnings are fixed so none of the errors are thrown when web service or website is used.</p>
				
				<p>Whenever you encounter an error message, this script should be the first place to check for a solution. It also prints out the entire trace of the error message that - while very detailed and often complicated - can often be the best way to find out why the error message happened in the first place.</p>
				
				<p>Wave Framework groups error messages together so that similar error messages are reported as single error message, which makes it easier when going through multiple bugs or error messages.</p>
				
				<p>When accessing this script, it automatically attempts to find an error log that has not been deleted yet.</p>
				
			<h2 id="index-compatibility-test">Compatibility Test</h2>
			
				<p><b>Location: /tools/compatibility.php</b></p>
				
				<p>This script is used to test your current server setup and PHP settings to see how compatible it is with WWW Framework.</p>
				
				<p>Compatibility script tests all the following:</p>
				
				<ul>
					<li>PHP Version</li>
					<li>Short Open Tag</li>
					<li>XML extension</li>
					<li>Zlib extension</li>
					<li>APC extension</li>
					<li>cURL extension or allow_url_fopen</li>
					<li>PDO and PDO drivers</li>
					<li>Fileinfo extension</li>
					<li>Mcrypt extension</li>
					<li>Zip extension</li>
					<li>FTP extension</li>
					<li>SimpleXML extension</li>
					<li>APC extension</li>
					<li>GD library extension</li>
					<li>Apache, URL rewrites and .htaccess presence</li>
					<li>Nginx and URL rewrites</li>
					<li>Filesystem folder write permissions</li>
				</ul>
			
			<h2 id="index-updater">Updater</h2>
			
				<p><b>Location: /tools/updater.php</b></p>
			
				<p>Updater script is used to update Wave Framework or software that is built on Wave Framework. Updater has a minimal user interface and update is processed over FTP. Updater script asks either a URL of the update archive file or a file upload with the archive (*.zip format), then the root directory (in case the FTP credentials have a different root directory), FTP username as well as FTP password.</p>
				
				<p>Updater requires FTP access to file system to work properly, since it requires permissions to add or overwrite files and folders that may not be possible with regular PHP permissions on some web servers.</p>
				
				<p>Once Updater script has FTP credentials and the archive file, it does the following:</p>
				
				<ul>
					<li>Unpacks the update archive to date specific subfolder '/filesystem/tmp/update-{Y-m-d-H-i-s}/'</li>
					<li>Creates system backup of current installation to '/filesystem/backups/{Y-m-d-H-i-s}.zip.tmp'</li>
					<li>Moves files from update folder to root folder of the system, overwriting where necessary</li>
					<li>If file 'www-updater.php' was included in archive root, then updater makes HTTP request to that file.</li>
				</ul>
				
				<p>This 'www-updater.php' file, if included in the script, can include additional version-specific guidelines. Updater script makes a HTTP request to this file and includes old version number for both system and Wave Framework itself as GET parameters 'www-version' and 'system-version'.</p>
				
				<p>For the Updater to work correctly, the files included in the archive must follow the 'root' folder structure of Wave Framework installation and also include .version file. This version file is checked to make sure that update version numbers (for all listed entries in .version file) are at least equal or larger than the number in the archive for both Wave Framework and system. Version numbers should be listed as PHP standard version format, like X.X.X.</p>
			
			<h2 id="index-test-suite">Test Suite</h2>
			
				<p><b>Location: /tools/tester.php</b></p>
				
				<p>Wave Framework includes a full test suite for writing tests for API's and running said tests. Tests themselves are defined in '/tools/tests/' subfolder and they can be run based on settings from the Test Suite tool. This Test Suite tool then returns the results from said tests and whether the tests failed or not. If tests included errors, then it also gives the full log of the errors.</p>
			
				<p>An example test case is included in '/tools/tests/' subfolder in 'example.ini' file. This test runs the 'example-get' command and checks if the response is accepted or not.</p>
				
				<p>To write a new test case, you need to create a new *.ini file in '/tests/' subfolder. It is recommended that you take a look at the example test and base your tests according to them. Basically a single test consists of three groups (defined between brackets). The first group is the API command that is being tested, the second and third groups are 'input' and 'output'. The input and output groups must follow the command group.</p>
				
				<p>You can define variables under the command group, these variables will be sent as fixed values to the API. For example you can define there if you wish to use cache or not.</p>
				
				<p>Input and output groups have to include variables (as array keys). Input group keys and values define what input data will be sent with the API request. This input data can also be dynamic which are defined by these values:</p>
				
				<ul>
					<li><b>:numeric:</b> - Sets a random number between 0 and 2147483647</li>
					<li><b>:numeric:1-20</b> - Sets a random number between 1 and 20</li>
					<li><b>:alpha:</b> - Sets a string up to 32 characters in length</li>
					<li><b>:alpha:1-10</b> - Sets a string with character length between 1 and 10</li>
					<li><b>:alphanumeric:</b> - Sets an alphanumeric string up to 32 characters in length</li>
					<li><b>:alphanumeric:1-10</b> - Sets an alphanumeric string with character length between 1 and 10</li>
					<li><b>:fixed:a,b,c</b> - Fixed value from the comma-separated list (either 'a', 'b' or 'c' in the example)</li>
				</ul>
					
				<p>Wave Framework generates these input variables automatically. If a dynamic variable is not set, then the test will get the value as-is.</p>
				
				<p>Output group keys and values define what value is expected from the API response. Thus if the output is different, then the test is considered as failed. As with input values, you can set a fixed value for output as well as a dynamic value. These are the allowed dynamic values:</p>
				
				<ul>
					<li><b>:numeric:</b> - Value must be numeric</li>
					<li><b>:numeric:1-20</b> - Value must be numeric between 1 and 20</li>
					<li><b>:alpha:</b> - Value must be a character string</li>
					<li><b>:alpha:1-10</b> - Value must be a character string between 1 and 10 characters in length</li>
					<li><b>:alphanumeric:</b> - Value must be a character string</li>
					<li><b>:alphanumeric:1-10</b> - Value must be a character string between 1 and 10 characters in length</li>
					<li><b>:fixed:a,b,c</b> - Value must be from a fixed list, either 'a', 'b' or 'c'.</li>
					<li><b>:any:</b> - Accepts any character, test would fail only if the output variable is not defined at all.</li>
					<li><b>:any:a-zA-Z0-9</b> - After ':any:' key you can write a regular expression for matched characters.</li>
				</ul>
				
				<p>You can assign both how many times tests are run as well as how much is the maximum execution time allocated for PHP when running the script. This is useful since sometimes it may be difficult to run a large amount of tests that are canceled by the server prematurely.</p>
				
				<p>If you want to run the same command multiple times, then add a postfix #1 (or some other number) into the group name.</p>
				
				<p>After the tests are run, the Test Suite shows a summary of how many tests failed and gives detailed information about each failed test.</p>
				
			<h2 id="index-calling-tools-through-factory">Calling Tools Through Factory</h2>
			
				<p>If you are building models, views and controllers, then sometimes it's necessary to call some of the usual developer tools within those objects as well. This is especially useful if you wish to clean all cache through the system rather than developer tool, since it is recommended to remove the /tools/ directory entirely from a live project.</p>
				
				<p>When you are writing functionality for Wave Framework MVC objects and for example you wish to clean all cache set by the system, then you can easily do it like this:</p>
				
<pre>
	<code>
	// This removes contents of all cache folders in /filesystem/ directory
	$this->callTool('cleaner','cache');
	</code>
</pre>

				<p>Other methods are also available, like:</p>
				
<pre>
	<code>
	// Returns an array that includes all the files and folders from specified folder
	$index=$this->callTool('indexer','/filesystem/');
	// Returns only an index of files
	$index=$this->callTool('indexer','/filesystem/','files');
	// .. and just folders
	$index=$this->callTool('indexer','/filesystem/','folders');
	// Gives the total filesize in bytes of all files in specified folder and its subfolders
	$size=$this->callTool('sizer','/filesystem/');
	// Deletes all cache (keywords work similarly to the cleaner Developer Tool
	$size=$this->callTool('cleaner','cache');
	</code>
</pre>
				

	</body>
</html>